
package hk.ces.oxfam.patch.transaction;

import hk.ces.oxfam.patch.TransactionPatch;
import hk.ces.oxfam.patch.TransactionStrategy;
import hk.ces.oxfam.patch.TransactionStrategyType;
import hk.ces.oxfam.patch.result.SQLResult;
import hk.ces.oxfam.patch.sql.ExcuteUtil;
import hk.ces.oxfam.patch.sql.PreparedSQL;
import hk.ces.oxfam.patch.sql.QueryUtil;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
import org.apache.log4j.Logger;

/**
 *
 * @author ReutyCheng
 */
@TransactionStrategy(TransactionStrategyType.ROLLBACK)
public class PersonInfoTypeToDonorPatch implements TransactionPatch
{
  private static final String DONOR = "DONOR";
  
  public void run(Connection connection) throws SQLException
  {
    List<Long> donorIds = this.getAllDonorIdFromTransaction(connection);
    Logger.getLogger(this.getClass()).debug("Totally Check Person[count=" + donorIds.size() + "]");
    
    int donorUpdatedResult = this.updateSelectedPersonInfoToDonor(connection, donorIds);
    Logger.getLogger(this.getClass()).debug("Totally update Donor[count=" + donorUpdatedResult + "]");
  }

  private List<Long> getAllDonorIdFromTransaction(Connection connection) throws SQLException
  {
    String sql = "select distinct donor_id from transaction";
    Object[] objects = new Object[]{};
    List<Long> donorIds = QueryUtil.column(connection, new PreparedSQL(sql, objects), 0, Long.class);

    return donorIds;
  }

  private int updateSelectedPersonInfoToDonor(Connection connection, List<Long> donorIds) throws SQLException
  {
    int resultCount = 0;

    int index = 0;
    for (Long donorId : donorIds)
    {
      if (isPersonHaveDonorInfo(connection, donorId))
      {
        Logger.getLogger(this.getClass()).debug(index + ". -- Person[id=" + donorId + "] have PersonInfoType is [DONOR] personinfo, Ignore this person for update PersonInfoType of [DONOR]");
      }
      else
      {
        Long nullPersonInfoTypeId = this.getPersonInfoTypeIsNullPersonInfoId(connection, donorId);
        if (nullPersonInfoTypeId == null || nullPersonInfoTypeId == 0L)
        {
          Logger.getLogger(this.getClass()).fatal(index + ". -- Person[id=" + donorId + "] have not got PersonInfoType is null PersonInfo is [DONOR] personinfo. Can't update this person");
        }
        else
        {
          String sql = "update personinfo set personinfotype = ? where id = ?";
          Object[] objects = new Object[] {
            DONOR,
            nullPersonInfoTypeId
          };
          int result = ExcuteUtil.excute(connection, new PreparedSQL(sql, objects));
          Logger.getLogger(this.getClass()).debug(index + ". Person[id=" + donorId + "] have NOT PersonInfoType is [DONOR] personinfo and have an null personinfotype personinfo[id=" + nullPersonInfoTypeId + "]. patch this person with PersonInfoType of [DONOR]");
          resultCount += result;
        }
      }

      index++;
    }

    return resultCount;
  }

  private Long getPersonInfoTypeIsNullPersonInfoId(Connection connection, Long donorId) throws SQLException
  {
    String sql = "select max(id) from personinfo where id in (select personinfolist_id from person_personinfo where person_id = ?) and personinfotype is null";
    Object[] params = new Object[]{donorId};
    SQLResult result = QueryUtil.query(connection, new PreparedSQL(sql, params));
    if (result.isResultsRmpty())
    {
      return 0L;
    }
    else
    {
      return result.getValue(0, 0, Long.class);
    }
  }

  private boolean isPersonHaveDonorInfo(Connection connection, Long donorId) throws SQLException
  {
    String sql = "select count(id) from personinfo where id in (select personinfolist_id from person_personinfo where person_id = ?) and personinfotype = ?";
    Object[] objects = new Object[] {
      donorId,
      DONOR
    };
    
    int count = QueryUtil.value(connection, new PreparedSQL(sql, objects), 0, 0, int.class);
    return count > 0;
  }
}
